﻿using System;
using CI.Organism;

namespace CI.Interfaces
{
    /// <summary>
    /// Synapse
    /// </summary>
    public interface ISynapse : ISynapticConnection
    {

        /// <summary>
        /// Input value from sensory or other neuron
        /// </summary>
        Int64 InputValue { get; }

        /// <summary>
        /// Input cycles wait until input value can be used
        /// This value gets decremented each check
        /// Simulates the lenght of a axiom and the delay associated with it
        /// </summary>
        Int64 InputWait { get; set; }

        /// <summary>
        /// Time to hold the the potential, eg how many cycles to maintain the value
        /// </summary>
        Int64 OutputHold { get; set; }

        /// <summary>
        /// Weight/Bias, is this going to veto eg negative number or permit eg positive number
        /// Acceptable values are postive and negative values
        /// </summary>
        double InputWeight { get; set; }

        /// <summary>
        /// Init Input Weight at synapse creation
        /// </summary>
        double InitInputWeight { get; set; }

        /// <summary>
        /// Output value read by the neuron
        /// </summary>
        Int64 OutputValue { get; }

        /// <summary>Last HeartBeat evaluation count for the Organism</summary>
        UInt32? LastEvalHeartbeatCount { get; }

        /// <summary>
        /// Target connected neurons/synapseIO
        /// </summary>
        ISynapticConnection TargetNotification { get; }

        /// <summary>
        /// Source connected neurons/synapseIO
        /// </summary>
        ISynapticConnection SourceNotification { get; }
        
        /// <summary>
        /// Take this parent synapse and create a new synapse to be put in the new child Organism
        /// Mutate the current synapse and return a new one, deep class level mutation
        /// </summary>
        /// <param name="mutationRate">mutation rate to be applied</param>
        /// <param name="childOrganism">child Organism it will be going into</param>
        /// <returns>new synapse for child</returns>
        ISynapse Mutate(double mutationRate, IOrganism childOrganism);

        /// <summary>
        /// Learning rule for the synapse
        /// </summary>
        ILearningRule LearningRule { get; set; }

        /// <summary>
        /// Called each clock tick cycle to calculate and populate the output value and call any delegates
        /// </summary>
        bool Evaluate(UInt32 neuralHB);

        /// <summary>
        /// notify once evaluation has been completed
        /// </summary>
        event Action EvaluationComplete;

        /// <summary>
        /// do a equals comparison of one synapse type to another only comparing the value types, no refference comparisons
        /// will call the check for learning rules
        /// </summary>
        /// <param name="synapse">synapse to compare against</param>
        /// <returns>true if equal value types</returns>
        bool EqualsValueTypes(ISynapse synapse);

        /// <summary>
        /// Reset values for processing
        /// </summary>
        void ResetValues();

        void AddSynapticConnectionTarget(ISynapticConnection synapticConnection);
        void AddSynapticConnectionSource(ISynapticConnection synapticConnection);
    }
}